﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;

namespace Ukagaka.Named
{
	using SimpleSettingPair = KeyValuePair<string, string>;

	/// <summary>
	/// キー値ペア形式設定ファイルの実装です
	/// </summary>
	internal static class SimpleSettingFile
	{
		/// <summary>
		/// 既定のエンコーディングを取得します
		/// </summary>
		public static Encoding DefaultEncoding { get; private set; }

		/// <summary>
		/// キー値ペア形式設定ファイルを初期化します
		/// </summary>
		static SimpleSettingFile( )
		{
			DefaultEncoding = Encoding.GetEncoding( "Shift_JIS" );
		}

		/// <summary>
		/// キー値ペア形式設定ファイルを読み込みます
		/// </summary>
		/// <param name="path">キー値ペア形式設定ファイル</param>
		/// <returns>キー値ペアを反復処理する列挙子</returns>
		public static IEnumerable<SimpleSettingPair> ReadLines( string path )
		{
			var encoding = GetEncoding( path );
			return ReadLines( path, encoding );
		}

		/// <summary>
		/// キー値ペア形式設定ファイルを読み込みます
		/// </summary>
		/// <param name="path">キー値ペア形式設定ファイル</param>
		/// <param name="encoding">キー値ペア形式設定ファイルのエンコーディング</param>
		/// <returns>キー値ペアを反復処理する列挙子</returns>
		public static IEnumerable<SimpleSettingPair> ReadLines( string path, Encoding encoding )
		{
			var contents = File.ReadLines( path, encoding );
			return ReadLines( contents );
		}

		/// <summary>
		/// キー値ペア形式設定ファイルを読み込みます
		/// </summary>
		/// <param name="path">キー値ペア形式設定ファイル内容</param>
		/// <returns>キー値ペアを反復処理する列挙子</returns>
		public static IEnumerable<SimpleSettingPair> ReadLines( IEnumerable<string> contents )
		{
			var result = default( SimpleSettingPair );
			return from x in contents
				   where TryParseLine( x, out result )
				   select result;
		}

		/// <summary>
		/// キー値ペア形式設定ファイルのエンコーディングを取得します
		/// </summary>
		/// <param name="path">キー値ペア形式設定ファイル</param>
		/// <returns>キー値ペア形式設定ファイルのエンコーディング</returns>
		public static Encoding GetEncoding( string path )
		{
			var linq = from x in ReadLines( path, Encoding.ASCII )
					   where string.Equals( "charset", x.Key, StringComparison.OrdinalIgnoreCase )
					   select Encoding.GetEncoding( x.Value );

			return linq.FirstOrDefault( ) ?? DefaultEncoding;
		}

		/// <summary>
		/// キー値ペア形式設定ファイル行からキー値ペアを取得します
		/// </summary>
		/// <param name="s">キー値ペア形式設定ファイル行</param>
		/// <param name="result">キー値ペア</param>
		/// <returns>正常に読み込まれた場合はtrue。それ以外の場合はfalse</returns>
		private static bool TryParseLine( string s, out SimpleSettingPair result )
		{
			var split = s.Split( new[ ] { ',' }, 2, StringSplitOptions.None );
			if ( 2 == split.Length )
			{
				var key = split[ 0 ].Trim( ).ToLowerInvariant( );
				var value = split[ 1 ].Trim( );
				{
					result = new SimpleSettingPair( key, value );
				}
				return true;
			}
			else
			{
				result = default( SimpleSettingPair );
				return false;
			}
		}
	}
}
